-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[GH-12] Added Ability to re-queue agenda Items. #89
Conversation
Codecov ReportBase: 24.56% // Head: 22.31% // Decreases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## master #89 +/- ##
==========================================
- Coverage 24.56% 22.31% -2.26%
==========================================
Files 7 7
Lines 403 484 +81
==========================================
+ Hits 99 108 +9
- Misses 287 358 +71
- Partials 17 18 +1
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. @mickmister The PR has now been seperated from the ones related to #66
i will check this and update you after some time. @hanzei |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work @sanjaydemansol! This is a really valuable feature, it's great to see it completed.
I have some requests and questions, including a request to write unit tests
webapp/src/actions/index.js
Outdated
export function requeueItem(itemId) { | ||
return async (dispatch, getState) => { | ||
const command = `/agenda requeue ${itemId}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is itemId
a post id? If so, it seems like having this requeue
slash command doesn't make much sense. 1/5 we should implement this as an HTTP endpoint instead, using the server-side ServeHTTP hook.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mickmister we had a discussion for same at #88 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, the slash command makes sense then. Maybe we change this to /agenda requeue post ${postId}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copied over from #88 (comment):
Made /agenda requeue
to support future options like
/agenda requeue all
# meeting canceled, I want to requeue all items to next meeting.
/agenda requeue last
# requeue last items
/agenda requeue last n
# requeue last n items
meetingDay := meetingDays[0] | ||
for _, day := range meetingDays { | ||
if todayWeekday <= day && day != dayToSkip { | ||
meetingDay = day | ||
break | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we write unit tests for this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
Message: fmt.Sprintf("#### %v %v) %v", hashtag, numQueueItems, originalPostMessage), | ||
}) | ||
if appErr != nil { | ||
return responsef("Error creating post: %s", appErr.Message) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error should be logged
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
messageRegexFormat = regexp.MustCompile(fmt.Sprintf(`(?m)^#### #%s(?P<date>.*) [0-9]+\) (?P<message>.*)?$`, prefix)) | ||
) | ||
|
||
if matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message); len(matchGroups) == 3 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to avoid this large indented block here
if matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message); len(matchGroups) == 3 { | |
matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message) | |
if len(matchGroups) != 3 { |
Then return an error in that if block, and continue on otherwise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great, done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems that this is not done
originalPostMessage := strings.TrimSpace(matchGroups[2]) | ||
|
||
today := time.Now() | ||
local, _ := time.LoadLocation("Local") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is Local
what's used elsewhere in this plugin?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, should I remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is usually used instead, or is the only instance of LoadLocation
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sanjaydemansol Please see my question above:
What is usually used instead, or is the only instance of
LoadLocation
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No localized methods are used anywhere. removing LoadLocation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
time.LoadLocation is stored in local and is used here at.
formattedDate, _ := time.ParseInLocation(hashtagDateFormat, originalPostDate, local)
server/command.go
Outdated
|
||
itemErr, numQueueItems := calculateQueItemNumber(args, p, hashtag) | ||
if itemErr != nil { | ||
return itemErr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return itemErr | |
return errors.Wrap(itemErr, "failed to calculate queue item number") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our plugin doesn't support returning this as HTTP response.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the problem is that itemErr
seems like it should be an error
but it's a *model.CommandResponse
. Maybe we can rename the variable commandResponse
?
server/command.go
Outdated
} | ||
return responsef(fmt.Sprintf("Item has been Re-queued to %v", hashtag)) | ||
} | ||
return responsef("Make sure, message is in required format!") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Under what circumstances would this occur? We definitely don't want to yell at the user 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced !
with .
.It occurs if Hashtag is not correctly formatted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0/5 it should be worded as
Please make sure the agenda hashtag is formatted properly.
webapp/src/index.js
Outdated
@@ -19,6 +19,10 @@ export default class Plugin { | |||
(channelId) => { | |||
store.dispatch(openMeetingSettingsModal(channelId)); | |||
}); | |||
|
|||
registry.registerPostDropdownMenuAction('Re-queue', (itemId) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
registerPostDropdownMenuAction
supports a third argument, a callback that returns boolean representing if we should show this action in the post menu. We should use this callback as an opportunity to check if the post is an agenda item post. If we determine that it is not an agenda item post, we should return false
in the callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We possibly want to use an identifier in post.props
to signal that it's an agenda post. But that wouldn't work with manually created agenda items.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0/5, for now we could ensure we only show Re-queue
option if a post starts with an #
. Your thoughts? @mickmister thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0/5, for now we could ensure we only show
Re-queue
option if a post starts with an#
I think this is a little too broad of a claim. Two reasons come to mind:
- Posts can start with
#
because they are using a header, and not a hash tag. For example,# I'm a header
renders as:
I'm a header
- Hashtags don't imply that it's an agenda hashtag.
I think we should go with the post.props
strategy. If someone wants to use the post menu to re-queue an item they created manually, too bad. cc @hanzei
Another option going along with this same strategy is for the server-side of the plugin to apply the post.props
mutation to the manually created agenda items during the MessageWillBePosted
and MessageWillBeUpdated
hooks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 for using post.props
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @mickmister @hanzei , nice approach.
Should I implement it in this PR or create a separate issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1/5 I'm thinking we should add it to this PR. @hanzei thoughts? I would want the change to block the release anyway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sanjaydemansol Note that the PR should be using post.props
to determine if the post is created by the plugin
@sanjaydemansol i found a issue but i was forgot to update here in PR, pls see this video. vokoscreenNG-2021-10-18_23-35-10.1.mp4. |
Possibly its due to #78 |
- updates based on feedback - bugfix for date allocation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as discussed with Ben, we already have ticket for other issue as #78 so this PR is LGTM
This PR has been automatically labelled "stale" because it hasn't had recent activity. |
@sanjaydemansol Heads up that this branch has conflicts |
The file |
/update-branch |
We don't have permissions to update this PR, please contact the submitter to apply the update. |
@hanzei reverted changes. |
@mickmister Please take another look |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @sanjaydemansol, I have a few more requests
t.Errorf("nextWeekdayDateInWeekSkippingDay() error = %v, wantErr %v", err, tt.wantErr) | ||
return | ||
} | ||
if !reflect.DeepEqual(got, &tt.want) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this also work?
if !reflect.DeepEqual(got, &tt.want) { | |
require.Equal(t, got, &tt.want) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mickmister tested code added require.Equal(t, got, &tt.want) {
, not working. test cases failed.
server/command.go
Outdated
} | ||
|
||
var ( | ||
messageRegexFormat = regexp.MustCompile(fmt.Sprintf(`(?m)^#### #%s(?P<date>.*) [0-9]+\) (?P<message>.*)?$`, prefix)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use regexp.Compile
instead of MustCompile
so we can handle the error and avoid a panic. As well as anywhere else we are calling MustCompile
inside of a function.
var patch, err = mpatch.PatchMethod(time.Now, func() time.Time { | ||
return time.Date(2021, 11, 15, 00, 00, 00, 0, time.UTC) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking we would pass in the value for now
in the function we're testing this with, rather than implicitly patching the value here. @sanjaydemansol What do you think?
We would modify nextWeekdayDateInWeekSkippingDay
to accept now
as a parameter:
now, _ := time.Date(2021, 11, 15, 00, 00, 00, 0, time.UTC)
got, err := nextWeekdayDateInWeekSkippingDay(now, tt.args.meetingDays, tt.args.nextWeek, tt.args.dayToSkip)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use now
for past and future cases hence, we should be fine with patching.
server/command.go
Outdated
postToBeReQueued, er := p.API.GetPost(oldPostID) | ||
if er != nil { | ||
return responsef("Error fetching post.") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0/5 We should log this error
postToBeReQueued, er := p.API.GetPost(oldPostID) | |
if er != nil { | |
return responsef("Error fetching post.") | |
} | |
postToBeReQueued, appErr := p.API.GetPost(oldPostID) | |
if appErr != nil { | |
return responsef("Error fetching post.") | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added Logs for error.
originalPostMessage := strings.TrimSpace(matchGroups[2]) | ||
|
||
today := time.Now() | ||
local, _ := time.LoadLocation("Local") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sanjaydemansol Please see my question above:
What is usually used instead, or is the only instance of
LoadLocation
?
server/command.go
Outdated
|
||
itemErr, numQueueItems := calculateQueItemNumber(args, p, hashtag) | ||
if itemErr != nil { | ||
return itemErr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the problem is that itemErr
seems like it should be an error
but it's a *model.CommandResponse
. Maybe we can rename the variable commandResponse
?
messageRegexFormat = regexp.MustCompile(fmt.Sprintf(`(?m)^#### #%s(?P<date>.*) [0-9]+\) (?P<message>.*)?$`, prefix)) | ||
) | ||
|
||
if matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message); len(matchGroups) == 3 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems that this is not done
webapp/src/actions/index.js
Outdated
export function requeueItem(postId) { | ||
return async (dispatch, getState) => { | ||
const command = `/agenda requeue ${postId}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we plan to support other commands in the future like this, I propose we be specific here that we are passing a post id #89 (comment)
const command = `/agenda requeue ${postId}`; | |
const command = `/agenda requeue post ${postId}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mickmister Updated code as per feedback
return nil, numQueueItems + 1 | ||
} | ||
|
||
func (p *Plugin) executeCommandReQueue(args *model.CommandArgs) *model.CommandResponse { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like this function was refactored, but we agreed it should be refactored and tested in this conversation
@mickmister Using |
@sanjaydemansol Unrelated to the error message you've posted, but we shouldn't be using the Is it possible for this regex to be defined on the package level, outside of the function? Then we can use |
@mickmister I think regex is already defined on the package level, outside of the function. |
@sanjaydemansol We should follow this convention: If the regex compilation requires a value at runtime, the compilation needs to occur in a function, so we should use If the regex compilation does not require a value at runtime, the compilation should occur on the package level, and we should use |
@mickmister updated code as per your suggestion. used MustCompile at package level. |
This PR has been automatically labelled "stale" because it hasn't had recent activity. /cc @aspleenic |
This PR has been automatically labelled "stale" because it hasn't had recent activity. |
@@ -19,6 +19,10 @@ export default class Plugin { | |||
(channelId) => { | |||
store.dispatch(openMeetingSettingsModal(channelId)); | |||
}); | |||
|
|||
registry.registerPostDropdownMenuAction('Re-queue', (postId) => { | |||
store.dispatch(requeueItem(postId)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to use post.props
to:
- declare a given post was made with the agenda plugin
- and check here to see if we should render the
Re-queue
item in the post dropdown menu
Fixes #12
Summary
Testing notes
Result:
It will be requeued to upcoming meeting date.
Ticket Link
#12